#include<iostream>
#include<cstring>
using std::cout;
using std::endl;
using std::cin;
class String 
{
public:
	String();
	String(const char *);
	String(const String &);
	~String();
	String &operator=(const String &);
	String &operator=(const char *);

	String &operator+=(const String &);
	String &operator+=(const char *);
	
	char &operator[](std::size_t index);
	const char &operator[](std::size_t index) const;
	
	std::size_t size() const;
	const char* c_str() const;
	
	friend bool operator==(const String &, const String &);
	friend bool operator!=(const String &, const String &);
	
	friend bool operator<(const String &, const String &);
	friend bool operator>(const String &, const String &);
	friend bool operator<=(const String &, const String &);
	friend bool operator>=(const String &, const String &);
	
	friend std::ostream &operator<<(std::ostream &os, const String &s);
	friend std::istream &operator>>(std::istream &is, String &s);

private:
	char * _pstr;
};

String operator+(const String &, const String &);
String operator+(const String &, const char *);
String operator+(const char *, const String &);


String::String()
:_pstr(new char[1]())
{
    strcpy(_pstr,"\0");
    cout<<_pstr<<"String"<<endl;
}
String::~String(){
    if(!_pstr){
        delete [] _pstr;
        _pstr = nullptr;
    }
    cout<<"~String"<<endl;
}
//文本常量赋值
String::String(const char *cha)
:_pstr(new char[strlen(cha)+1]())
{
    strcpy(_pstr,cha);
    cout<<"const cope"<<endl;    
}
//拷贝构造函数
String::String(const String &cha)
    :_pstr(new char[cha.size()+1]())
{
   strcpy(_pstr,cha.c_str());
    cout<<"cope"<<endl;
}
//获取 自定义类string 的大小
std::size_t String::size() const{
    return strlen(_pstr);
}
//转化成char*类型
const char* String::c_str() const{
    return _pstr;
}
//赋值重载
String &String::operator=(const String &cha){
    //先把类原来的空间释放
    //判断是不是自赋值
    if(strcmp(cha.c_str(),_pstr)==0){
       return *this; 
    }
    //不是就开始重新赋值
    if(!_pstr){
        delete [] _pstr;
    }
    //重新给空间 这里不能浅拷贝  会涉及doublefree的问题
    _pstr = new char[cha.size()+1]();
    strcpy(_pstr,cha.c_str());
    cout<<"= string"<<endl;
    //讲赋值完成的string返回
    return *this;
}

String &String::operator=(const char *cha){
    //还是看下是不是自赋值
    if(strcmp(cha,_pstr)==0){
        return *this;
    }
    if(!_pstr){
        delete [] _pstr;
    }
    _pstr = new char [strlen(cha)+1]();
    strcpy(_pstr,cha);
    cout<<"= char*"<<endl;
    return *this;
}

String & String::operator+=(const String &cha){
    //string 拼接
    
    strcat(_pstr,cha.c_str());
    return *this;
}
String& String::operator+=(const char *cha){
    strcat(_pstr,cha);
    return *this;
}


//[]重载 必须是成员函数 根据 给的下标获取字符
char &String::operator[](std::size_t index){

    char &c = _pstr[index];
  //  c = 'W';
    return c;
}

const char &String::operator[](std::size_t index) const{
    char &c = _pstr[index];
    return c;
}

bool operator==(const String &cha, const String &cha1){
    if(strcmp(cha.c_str(),cha1.c_str())==0){
        return true;
    }return false;
}
bool operator!=(const String &cha, const String &cha1){
    if(strcmp(cha.c_str(),cha1.c_str())!=0){
        return true;

    }
    return false;
}

bool operator<(const String &cha, const String &cha1){
    if(strcmp(cha.c_str(),cha1.c_str())<0){
        return true;
    }return false;
}
bool operator>(const String &cha, const String &cha1){
    if(strcmp(cha.c_str(),cha1.c_str())>0){
        return true;
    }
    return false;
}
//输出流重载 可直接输出类的值
std::ostream &operator<<(std::ostream &os, const String &s){
    os<<s._pstr;
    return os;
}
std::istream &operator>>(std::istream &is, String &s){
    is>>s._pstr;
    return is;
} 
 //拼接 返回临时string
String operator+(const String &cha, const String &cha1){
    String st(cha);
    st+=cha1;
    return st;
}
String operator+(const String &cha, const char *cha1){
    String st(cha);
    st+=cha1;
    return st;
}
String operator+(const char *cha, const String &cha1){
    String st(cha);
    st +=cha1;
    return st;
}

void test(){
    String st;
    String st1("hello");
    String st2(st1);
    st = st2;
    st = "hello";
    //可以通过下标访问
    //私有数据成员是无法在类外访问
    //st._pstr[0];
    st2[2] = 'C';
    cout<<st2[2]<<endl;
    
    const String st3="my_world";
    cout<<st3[3]<<endl;

    cout<<(st!=st1)<<endl;
    
    cout<<(st>st3)<<endl;

    String st4;
    cin>>st4;
    cout<<st4<<endl;
    
    st4 = st+st2;
    cout<<st4<<endl;

    st4 = st+"dasda";
    cout<<st4<<endl;
    st4 = "dad"+st;
    cout<<st4<<endl;
    return ;
}
int main(){
    test();
}
